home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / packet / tf27bsrc / l2c.c < prev    next >
C/C++ Source or Header  |  1994-09-16  |  50KB  |  993 lines

  1. /**************************************************************************\
  2. *                                                                          *
  3. *                                                                          *
  4. *    *****                      *****                                      *
  5. *      *****                  *****                                        *
  6. *        *****              *****                                          *
  7. *          *****          *****                                            *
  8. *            *****      *****                                              *
  9. *              *****  *****                                                *
  10. *            *****      *****                                              *
  11. *          *****          *****          The Firmware. The Net.            *
  12. *        *****              *****        Portable. Compatible.             *
  13. *      *****                  *****      Public Domain.                    *
  14. *    *****                      *****    By NORD><LINK.                    *
  15. *                                                                          *
  16. *                                                                          *
  17. *                                                                          *
  18. *    L2C.C   -   Level 2, Teil 3                                           *
  19. *                                                                          *
  20. *    angelegt:      DC4OX                                                  *
  21. *    modifiziert:   DL8ZAW, 25.04.91                                       *
  22. *                   sdl2fr():  Bei DAMA Betrieb kein kicktx(0)             *
  23. *                   l2tolx():  DAMA Betrieb einschalten bei Connect und    *
  24. *                              DAMA-Master, DAMA Betrieb ausschalten, wenn *
  25. *                              Disconnect und keine weiteren DAMA Masters  *
  26. *                                                                          *
  27. *                   DL8ZAW, 04.05.91                                       *
  28. *                   clrT1():   RTT-Messung beenden.                        *
  29. *                              SRTT aus gemessenem RTT-Wert berechnen:     *
  30. *                              - bei gestiegenem RTT:                      *
  31. *                                SRTT' = (a1 x SRTT + RTT) / (a1 + 1)      *
  32. *                              - bei gefallenem RTT:                       *
  33. *                                SRTT' = (a2 x SRTT + RTT) / (a2 + 1)      *
  34. *                   setT1():   RTT-Messung starten.                        *
  35. *                              T1 nach aktuellem SRTT-Wert setzen:         *
  36. *                              T1 = a3 x SRTT                              *
  37. *                   (a1, a2 und a3 koennen mit @A1, @A2 und @A3-Befehlen   *
  38. *                    geaendert werden.)                                    *
  39. *                                                                          *
  40. *                   setT2():   Im DAMA-Modus T2 auf 1 setzen, d.h.         *
  41. *                              praktisch auf T2-Timer verzichten.          *
  42. *                                                                          *
  43. *                   DB2OS, 03.09.91:                                       *
  44. *                   clrT1():   Neue Grenzen in der Plausibilitätsabfrage   *
  45. *                              für den RTT, aufrund verbesserter RTT-      *
  46. *                              Zeitbestimmung im L2B.C, sdi().             *
  47. *                                                                          *
  48. *                   DL8ZAW, 27.03.92                                       *
  49. *                   Code, der nicht fuer TheFirmware benoetigt wird        *
  50. *                   entfernt.                                              *
  51. *                                                                          *
  52. *                   DB2OS, 21.07.93                                        *
  53. *                   clrT1():  DG6MAY - möglicher Zahlenüberlauf bei        *
  54. *                             SRTT-Berechnung. Daher in der Zwischen-      *
  55. *                             berechnung in 100ms rechnen...               *
  56. *                   DL4YBG, 23.10.93                                       *
  57. *                   setT1():  T1 aus IT1 fuellen                           *
  58. *                   clrT1():  Aenderung nach DG6MAY rueckgaengig gemacht,  *
  59. *                             Grenzwerte RTTMIN und RTTMAX eingefuehrt     *
  60. *                                                                          *
  61. *                   DG2FEF, 18.07.94                                       *
  62. *                   clrT1(),: SRTT-Berechnung rausgeworfen.                *
  63. *                   setT1()                                                *
  64. *                   clrRTT(): SRTT-Berechung findet jetzt hier statt       *
  65. *                   stxcfr(): Als Slave DISC^ bzw. SABM^ senden statt      *
  66. *                             DISC+ bzw. SABM+                             *
  67. *                   istome(): Alias-Abfrage entfernt.                      *
  68. *                                                                          *
  69. *                   DG2FEF, 13.08.94                                       *
  70. *                   stxcfr(): Änderung wieder rückgängig gemacht, dafür    *
  71. *                             nun Patches in xrrc() xsabm() xdisc()        *
  72. *                                                                          *
  73. *                   DB2OS, 12.08.94                                        *
  74. *                             Bei der SRTT-Berechnung keine getrennten     *
  75. *                             A1,A2 mehr.                                  *
  76. *                                                                          *
  77. *                   DB2OS/DJ9KC, 15.09.94                                  *
  78. *                   xrrr():   Bestätigen mit I-Frames ermöglichen.         *
  79. *                                                                          *
  80. *                   DB2OS, 16.09.94                                        *
  81. *                   xrrr():   Änderung noch einmal zurückgestellt, da noch *
  82. *                             nicht mit FLEXNET-DAMA kompatibel.           *
  83. *                             Änderung ist aber in Aussicht gestellt..     *
  84. \**************************************************************************/
  85.  
  86.  
  87.  
  88.  
  89.  
  90. /*                                                             Includes   */
  91. /**************************************************************************/
  92.  
  93. #include "all.h"         /* allgemeine Festlegungen                       */
  94. #include "l2.h"          /* Festlegungen/Datenstrukturen fuer den Level 2 */
  95. #include "l2s.h"         /* Zugriff auf die State-Tabellen                */
  96. #include "l2ext.h"       /* globale Variable / nicht int-Funktionen       */
  97.  
  98.  
  99.  
  100.  
  101.  
  102. /**************************************************************************\
  103. *                                                                          *
  104. * action      :  Zustandsuebergangsfunktionen der Level-2-Statetable       *
  105. *                (x.../t...), Level-2-Timer setzen/aufloesen (setT./clrT.) *
  106. *                und Utilities fuer diese Funktionen.                      *
  107. *                                                                          *
  108. *   t2rrr()   -  Timer 2 setzen, nach Ablauf RR als Response zu senden     *
  109. *   t2rnrr()  -  Timer 2 setzen, nach Ablauf RNR als Response zu senden    *
  110. *   t2rejr()  -  Timer 2 setzen, nach Ablauf REJ als Response zu senden    *
  111. *                                                                          *
  112. *   xnull()   -  nichts tun                                                *
  113. *                                                                          *
  114. *   xrrc()    -  RR als Command senden      [DG2FEF Nicht bei DAMA]        *
  115. *   xrrr()    -  RR als Response senden                                    *
  116. *   xrnrc()   -  RNR als Command senden                                    *
  117. *   xrnrr()   -  RNR als Response senden                                   *
  118. *   xrejr()   -  REJ als Response senden                                   *
  119. *                                                                          *
  120. *   xdm()     -  DM senden                                                 *
  121. *   xua()     -  UA senden                                                 *
  122. *   xsabm()   -  SABM senden                [DG2FEF Bei DAMA ohne Pollbit] *
  123. *   xdisc()   -  DISC senden                [DG2FEF Bei DAMA ohne Pollbit] *
  124. *                                                                          *
  125. *   xfrmr()   -  FRMR senden (-> L2E.C)                                    *
  126. *                                                                          *
  127. *   setT1()   -  Timer 1 setzen und Timer 3 loeschen                       *
  128. *   clrT1()   -  Timer 1 und tries loeschen, Timer 3 setzen                *
  129. *   setT2()   -  Timer 2 und nach Ablauf zu sendenden Frametyp setzen      *
  130. *   clrT2()   -  Timer 2 und nach Ablauf zu sendenden Frametyp loeschen    *
  131. *   setT3()   -  Timer 3 setzen, wenn Version 2 Protokoll benutzt wird     *
  132. *   clrT3()   -  Timer 3 loeschen                                          *
  133. *                                                                          *
  134. *   sendS()   -  Supervisory-Frame fuer Sendung aufbauen, Timer 2          *
  135. *                loeschen, Frame senden                                    *
  136. *   sdfrmr()  -  FRMR-Frame fuer Sendung aufbauen und senden (-> L2E.C)    *
  137. *                                                                          *
  138. \**************************************************************************/
  139.  
  140. VOID t2rrr()  { setT2(L2CRR);                                              }
  141.  
  142. VOID t2rnrr() { setT2(L2CRNR);                                             }
  143.  
  144. VOID t2rejr() { setT2(L2CREJ);                                             }
  145.  
  146. VOID setT1()
  147. {
  148.   lnkpoi->T1 = lnkpoi->IT1;     /* Timer1 aktualisieren [DL4YBG] */
  149.   clrT3();
  150. }
  151.  
  152. /**************************************************************************\
  153. *                                                                          *
  154. * "clear Round Trip Timer" [DG2FEF]                                        *
  155. *                                                                          *
  156. * RTT-Messung beenden, SRTT und T1-Startwert berechnen                     *
  157. * RTT-Messung ist nur gültig, wenn T1 zwischendurch nicht abgelaufen war   *
  158. * ansonsten ist irgendwas schiefgelaufen und die ermittelte RTT möglicher- *
  159. * weise fehlerhaft                                                         *
  160. *                                                                          *
  161. \**************************************************************************/
  162. VOID clrRTT()
  163. {
  164.   if (   !(lnkpoi->flag & L2FDIRTY)  /* RTT-Messung "schmutzig", T1 war  */
  165.       && lnkpoi->RTT != 0)           /* wohl mal abgelaufen              */
  166.     {
  167.     if (lnkpoi->RTT < RTTMIN)
  168.       lnkpoi->RTT = RTTMIN;
  169.     else if (lnkpoi->RTT > RTTMAX)
  170.       lnkpoi->RTT = RTTMAX;
  171.     lnkpoi->SRTT = (10*(lnkpoi->SRTT)+(lnkpoi->RTT))/(11);    /* [DB2OS] */
  172.     lnkpoi->IT1 = A3par * lnkpoi->SRTT;
  173.     }
  174.   lnkpoi->RTT = 0;
  175.   lnkpoi->flag &= ~L2FDIRTY;
  176. }
  177.  
  178.  
  179. /**************************************************************************\
  180. * "clear Timer1"                                                           *
  181. * FEF                                                                      *
  182. *                                                                          *
  183. \**************************************************************************/
  184. VOID clrT1()
  185. {
  186.   lnkpoi->T1  = 0;
  187.   lnkpoi->tries = 0;
  188.   setT3();
  189. }
  190.  
  191. VOID setT2(Stype)
  192. char Stype;
  193. {
  194.   lnkpoi->RStype = Stype;
  195.   lnkpoi->T2 = T2par;
  196. }
  197.  
  198. VOID clrT2()  { lnkpoi->RStype = 0; lnkpoi->T2 = 0;                        }
  199.  
  200. VOID setT3()  { lnkpoi->T3 = damaok ? 18000 : T3par;                       }
  201.  
  202. VOID clrT3()  { lnkpoi->T3 = 0;                                            }
  203.  
  204. VOID xnull()  {                                                            }
  205.  
  206. VOID xrrc()   { if (!(lnkpoi->flag & L2FDAMA)) { stxcfr(); xrrr(); }       }
  207.  
  208. #ifdef FLEXNETOK          /* Zur Zeit nur mit TheNetNode kompatibel!!!    */
  209. VOID xrrr()               /* Bei DAMA nur RR senden, wenn keine Infos zu  */
  210. {                         /* senden sind oder kein IXFER möglich ist..    */
  211.   if (    damaok == 0
  212.       || (damaok == 1 && (lnkpoi->tosend == 0 || lnkpoi->state != L2SIXFER))
  213.      )
  214.     sendS(L2CRR);
  215. }
  216. #else
  217. VOID xrrr()   { sendS(L2CRR);                                              }
  218. #endif
  219.  
  220.  
  221. VOID xrnrc()  { stxcfr(); xrnrr();                                         }
  222.  
  223. VOID xrnrr()  { sendS(L2CRNR);                                             }
  224.  
  225. VOID xrejr()  { sendS(L2CREJ);                                             }
  226.  
  227. VOID sendS(control) char control;
  228.               { clrT2(); txfctl=setNR(control);
  229.                 sdl2fr(makfhd(!txfCR ? L2FUS : (L2FUS | L2FT1ST))); }
  230.  
  231. VOID xdm()    { txfctl = L2CDM; sdl2fr(makfhd(L2FUS));                     }
  232.  
  233. VOID xua()    { txfctl = L2CUA; sdl2fr(makfhd(L2FUS));                     }
  234.  
  235. VOID xsabm()  { if (damaok) { stxfad(); txfPF = 0; txfCR = L2CCR; } else
  236.                 stxcfr(); txfctl = L2CSABM; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
  237.  
  238. VOID xdisc()  { if (damaok) { stxfad(); txfPF = 0; txfCR = L2CCR; } else
  239.                 stxcfr(); txfctl = L2CDISC; sdl2fr(makfhd(L2FUS|L2FT1ST)); }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. /**************************************************************************\
  246. *                                                                          *
  247. * "set tx command frame"                                                   *
  248. *                                                                          *
  249. * TX-Frame-Adressierung setzen (siehe stxfad()) und Frame zum Kommando-    *
  250. * frame machen mit gesetztem Pollbit (txfCR,txfPF).                        *
  251. *                                                                          *
  252. \**************************************************************************/
  253.  
  254. VOID stxcfr()
  255.   {
  256.     stxfad();                           /* Adressierung                   */
  257.     txfCR = L2CCR;                      /* Command !                      */
  258.     txfPF = L2CPF;                      /* Pollbit !                      */
  259.   }
  260.  
  261.  
  262. /**************************************************************************\
  263. *                                                                          *
  264. * "set tx frame address"                                                   *
  265. *                                                                          *
  266. * Adressierung des aktuellen Sendeframes (txfhdr, txfprt) setzen aus den   *
  267. * im aktuellen Linkblock (lnkpoi) gegebenen Parametern (srcid, destid,     *
  268. * viaidl, liport).                                                         *
  269. *                                                                          *
  270. \**************************************************************************/
  271.  
  272. VOID stxfad()
  273.   {
  274.     cpyid(txfhdr + L2IDLEN,lnkpoi->srcid);        /* von ...              */
  275.     cpyid(txfhdr,lnkpoi->dstid);                  /* nach ...             */
  276.     cpyidl(txfhdr + L2ILEN,lnkpoi->viaidl);       /* ueber ...            */
  277.     txfprt = lnkpoi->liport;                      /* auf Port ...         */
  278.   }
  279.  
  280.  
  281.  
  282.  
  283.  
  284. /**************************************************************************\
  285. *                                                                          *
  286. * "set NR"                                                                 *
  287. *                                                                          *
  288. * Im aktuellen Linkblock (lnkpoi) die zuletzt gesendete N(R) (ltxdNR) auf  *
  289. * V(R) (VR) setzen und Framecontrolbyte control fuer Frameaussendung mit   *
  290. * der N(R) versehen und zurueckgeben.                                      *
  291. *                                                                          *
  292. * Return :  control mit N(R) versehen                                      *
  293. *                                                                          *
  294. \**************************************************************************/
  295.  
  296. unsigned setNR(control)
  297.  
  298. char control;
  299.  
  300.   {
  301.     lnkpoi->ltxdNR = lnkpoi->VR;             /* neue N(R)                 */
  302.     return((lnkpoi->VR << 5) | control);     /* N(R) ins Kontrollfeld     */
  303.   }
  304.  
  305.  
  306.  
  307.  
  308.  
  309. /**************************************************************************\
  310. *                                                                          *
  311. * "send level 2 frame"                                                     *
  312. *                                                                          *
  313. * Framebuffer, auf dessen Kopf fbp zeigt, rewinden und in die dem Port     *
  314. * (l2port) entsprechende Level-2-Sendeframeliste einhaengen, wenn noch     *
  315. * genug Buffer im System frei sind. Andernfalls nicht senden, sondern      *
  316. * sofort in die Gesendet-Liste (stfl) einhaengen. Bei TheNet die           *
  317. * Sendeaktiviatetsvariable (istraf) des entsprechenden Ports setzen.       *
  318. * Bei DAMA Betrieb kein kicktx()                                           *
  319. *                                                                          *
  320. \**************************************************************************/
  321.  
  322. VOID sdl2fr(fbp)
  323.  
  324. MBHEAD *fbp;
  325.  
  326.   {
  327.     static unsigned port;               /* Portnummer                     */
  328.  
  329.     port = fbp->l2port;                 /* Portnummer holen               */
  330.     if (nmbfre > TXBREMSE)              /* noch genug Buffer ?            */
  331.       {
  332.         rwndmb(fbp);                    /* ja   - Framebuffer rewinden    */
  333.         DIinc();                        /*        Listenkonsistenz !      */
  334.         relink(fbp,txl2fl[port].tail);  /*        Frame in Sendeliste     */
  335.         if (!damaok || sendok)          /* DAMA:  nicht senden            */
  336.           {
  337.             kicktx(port);               /*        es ist sofort zu senden */
  338.             tosend = 0;
  339.           }
  340.         else
  341.           tosend = 1;                   /* DAMA:  es ist spaeter zu senden*/
  342.         decEI();                        /*        Interrupts w. erlauben  */
  343.  
  344.       }
  345.     else                                /* nein - Frame einfach sofort    */
  346.       relink(fbp,stfl.tail);            /*        als gesendet betrachten */
  347.   }
  348.  
  349.  
  350.  
  351.  
  352.  
  353. /**************************************************************************\
  354. *                                                                          *
  355. * "copy frame buffer"                                                      *
  356. *                                                                          *
  357. * Framebuffer, auf den fbp zeigt, komplett mit Inhalt kopieren. Dazu freie *
  358. * Buffer allokieren, Portnummer (l1port) wird kopiert, Bufferzeiger (mbbp) *
  359. * und Getcounter (mbgc) werden nicht kopiert, bleiben aber im Quellframe   *
  360. * erhalten.                                                                *
  361. *                                                                          *
  362. * Return :  Zeiger auf Kopf des kopierten Framebuffers                     *
  363. *                                                                          *
  364. \**************************************************************************/
  365.  
  366. MBHEAD *cpyfb(fbp)
  367.  
  368. MBHEAD *fbp;
  369.  
  370.   {
  371.     static char       *savmbbp;         /* mbbp-Sicherung                 */
  372.     static unsigned    savmbgc;         /* mbgc-Sicherung                 */
  373.     static MBHEAD     *newfbp;          /* Zeiger auf die Kopie           */
  374.  
  375.     savmbbp = fbp->mbbp;                /* mbbp sichern                   */
  376.     savmbgc = fbp->mbgc;                /* mbgc sichern                   */
  377.     rwndmb(fbp);                        /* Quellframe rewinden            */
  378.     newfbp = allocb();                  /* Kopf der Kopie allokieren      */
  379.     while (fbp->mbgc < fbp->mbpc)       /* Daten byteweise kopieren       */
  380.       putchr(getchr(fbp),newfbp);
  381.     newfbp->l2port = fbp->l2port;       /* Portnummer kopieren            */
  382.     fbp->mbbp = savmbbp;                /* mbbp wieder auf alten Wert     */
  383.     fbp->mbgc = savmbgc;                /* mbgc wieder auf alten Wert     */
  384.     return (newfbp);                    /* Zeiger auf Kopf der Kopie      */
  385.   }
  386.  
  387.  
  388.  
  389.  
  390.  
  391. /**************************************************************************\
  392. *                                                                          *
  393. * "take frame head"                                                        *
  394. *                                                                          *
  395. * Adresskopf und Kontrollbyte des Frames aus dem Framebuffer, auf dessen   *
  396. * Kopf fbp zeigt, analysieren. Diese Funktion ist die erste, die auf ein   *
  397. * empfangenes Frame angewandt wird.                                        *
  398. *                                                                          *
  399. *                                                                          *
  400. * Folgende Parameter werden bei der Analyse gesetzt (siehe auch L2V.C) :   *
  401. *                                                                          *
  402. *    rxfhdr, rxfV2, rxfPF, rxfCR, rxfctl, rxfprt                           *
  403. *                                                                          *
  404. *                                                                          *
  405. * Folgende Parameter werden nach der Analyse gesetzt fuer ein moegliches   *
  406. * Antwortframe :                                                           *
  407. *                                                                          *
  408. *   txfhdr  = Quell- und Zielcall aus rxfhdr, aber vertauscht, plus        *
  409. *             reverse via-Liste aus rxfhdr                                 *
  410. *   txfV2   = rxfV2                                                        *
  411. *   txfPF   = rxfPF                                                        *
  412. *   txfCR   = 0, Response !                                                *
  413. *   txfprt  = rxfprt                                                       *
  414. *                                                                          *
  415. *                                                                          *
  416. * Return :  TRUE  - das Frame hat einen gueltigen AX.25-Framekopf          *
  417. *           FALSE - sonst                                                  *
  418. *                                                                          *
  419. \**************************************************************************/
  420.  
  421. BOOLEAN takfhd(fbp)
  422.  
  423. MBHEAD *fbp;
  424.  
  425.   {
  426.     static char *viap;                            /* Zeiger in via-Liste  */
  427.     static char *source;                          /* Quellzeiger Kopien   */
  428.     static char *dest;                            /* Zielzeiger Kopien    */
  429.  
  430.     rwndmb(fbp);                                  /* Frame von vorne      */
  431.     if (    !getfid(rxfhdr,fbp)                   /* Zielcall holen       */
  432.          || ((rxfhdr[L2IDLEN - 1] & L2CEOA) != 0) /* (Ende nach 1. Call ?)*/
  433.          || !getfid(rxfhdr + L2IDLEN,fbp)         /* Quellcall holen      */
  434.        ) return (FALSE);                          /* ... schon Fehler     */
  435.     viap = rxfhdr + L2ILEN;                       /* ab hier via-Liste    */
  436.     if (!(rxfhdr[L2ILEN - 1] & L2CEOA))           /* via-Liste da ?       */
  437.       LOOP
  438.         {                                               /* alle via's     */
  439.           if (!getfid(viap,fbp)) return (FALSE);        /* Call holen     */
  440.           viap += L2IDLEN;                              /* naechstes Call */
  441.           if ((*(viap - 1) & L2CEOA) != 0) break;       /* Ende der Liste */
  442.           if (viap >= rxfhdr + L2AFLEN) return (FALSE); /* zu lange Liste */
  443.         }
  444.     *viap = '\0';                                       /* Listenende !   */
  445.     if (fbp->mbgc == fbp->mbpc) return (FALSE);         /* Frame zu kurz  */
  446.     rxfctl = getchr(fbp);                               /* Controlbyte    */
  447.  
  448.  
  449.     /* Protokollversion feststellen und danach C/R und P/F festlegen */
  450.  
  451.     if ( (rxfV2 = ((rxfhdr[L2IDLEN - 1] ^ rxfhdr[L2ILEN - 1]) & L2CCR) != 0)
  452.          == YES
  453.        )
  454.       {                                           /* nur Version 2 :      */
  455.         rxfCR = rxfhdr[L2IDLEN - 1] & L2CCR;      /*   Command/Response   */
  456.         rxfPF = rxfctl & L2CPF;                   /*   Poll/Final         */
  457.       }
  458.     else                                          /* Version 1 :          */
  459.       rxfPF = rxfCR = 0;                          /* P/F u. C/R sinnlos   */
  460.  
  461.     rxfctl &= ~L2CPF;                             /* P/F Control loeschen */
  462.     rxfprt = fbp->l2port;                         /* Portnummer holen     */
  463.  
  464.  
  465.     /* Antwort-Sendeframeaufbau */
  466.  
  467.     txfCR = 0;                                    /* Response !           */
  468.     txfV2 = rxfV2;                                /* Version              */
  469.     txfPF = rxfPF;                                /* Poll/Final           */
  470.     txfprt = rxfprt;                              /* Portnummer           */
  471.     cpyid(txfhdr,rxfhdr + L2IDLEN);               /* TX-Ziel = RX-Quelle  */
  472.     cpyid(txfhdr + L2IDLEN,rxfhdr);               /* TX-Quelle = RX-Ziel  */
  473.     source = rxfhdr + L2ILEN;                     /* TX-Antwort-via-Liste */
  474.     dest = txfhdr + L2ILEN;                       /* ist, falls vorhanden */
  475.     while (*source != '\0') source += L2IDLEN;    /* reverse RX-via-Liste */
  476.     while (source != rxfhdr + L2ILEN)
  477.       {
  478.         source -= L2IDLEN;
  479.         cpyid(dest,source);
  480.         dest += L2IDLEN;
  481.       }
  482.     *dest = '\0';                                 /* Listenende !         */
  483.  
  484.     return (TRUE);                                /* Frame soweit okay !  */
  485.   }
  486.  
  487.  
  488.  
  489.  
  490.  
  491. /**************************************************************************\
  492. *                                                                          *
  493. * "get frame ID"                                                           *
  494. *                                                                          *
  495. * Die naechste ID nach dest (Call + SSID, SSID wie im Frame) holen aus dem *
  496. * Buffer (Call + SSID, beide wie im Frame), auf dessen Kopf mbhd zeigt.    *
  497. * Die geholte SSID enthaelt das End-Of-Address-Bit unveraendert.           *
  498. *                                                                          *
  499. * Return :  TRUE  - die naechste ID (Call + SSID) wurde richtig geholt     *
  500. *           FALSE - es hat sich ein Fehler ereignet                        *
  501. *                                                                          *
  502. \**************************************************************************/
  503.  
  504. BOOLEAN getfid(dest,mbhd)
  505.  
  506. char     *dest;
  507. MBHEAD   *mbhd;
  508.  
  509.   {
  510.     static char       c;                /* aktuelles Zeichen aus Buffer   */
  511.     static unsigned   n;                /* Zaehler Call-Laenge            */
  512.  
  513.     if (mbhd->mbpc - mbhd->mbgc < L2IDLEN)        /* im Buffer nicht mehr */
  514.       return (FALSE);                             /* genug Bytes fuer ID  */
  515.     for (n = 0; n < L2CALEN; ++n)                 /* Call byteweise holen */
  516.       {
  517.         if (((c = getchr(mbhd)) & L2CEOA) != 0)   /* Adressfeld zu frueh  */
  518.           return (FALSE);                         /* zuende               */
  519.         *dest++ = (c >> 1) & 0x7F;                /* Framecall -> ASCII   */
  520.       }
  521.     *dest = getchr(mbhd);               /* SSID holen, EOA bleibt         */
  522.     return (TRUE);
  523.   }
  524.  
  525.  
  526.  
  527.  
  528.  
  529. /**************************************************************************\
  530. *                                                                          *
  531. * "make frame head"                                                        *
  532. *                                                                          *
  533. * Neues Frame aufbauen aus den txf...-Parametern. Es werden neue Buffer    *
  534. * fuer das Frame allokiert, der aktuelle Linkblock (lnkpoi) wird           *
  535. * eingetragen und fflag fuer das Frameflag l2fflg.                         *
  536. *                                                                          *
  537. * Return :  Zeiger auf Framebufferkopf des neu erzeugten Frames            *
  538. *                                                                          *
  539. \**************************************************************************/
  540.  
  541. MBHEAD *makfhd(fflag)
  542.  
  543. unsigned fflag;
  544.  
  545.   {
  546.     static MBHEAD *fbp;                           /* Zeiger auf Kopf      */
  547.  
  548.     if (txfV2 == YES)                             /* wenn Version 2 ...   */
  549.       {
  550.         txfhdr[L2IDLEN - 1] |= txfCR;             /* ... C-Bits setzen    */
  551.         txfhdr[L2ILEN - 1] |= txfCR ^ L2CCR;
  552.       }
  553.     putfid(txfhdr,fbp = allocb());                /* neuer Buffer, Ziel   */
  554.     putfid(txfhdr + L2IDLEN,fbp);                 /* Quellcall            */
  555.     putvia(txfhdr + L2ILEN,fbp);                  /* via-Liste            */
  556.     putchr(!txfV2 ? txfctl : txfctl | txfPF,fbp); /* Control + P/F        */
  557.     fbp->l2link = lnkpoi;                         /* Verweis Linkblock    */
  558.     fbp->type = 2;                                /* Level 2 !            */
  559.     fbp->l2fflg = fflag;                          /* Frameflag            */
  560.     fbp->l2port = txfprt;                         /* Portnummer           */
  561.     return (fbp);                                 /* Kopfzeiger zurueck   */
  562.   }
  563.  
  564.  
  565.  
  566.  
  567.  
  568. /**************************************************************************\
  569. *                                                                          *
  570. * "put via"                                                                *
  571. *                                                                          *
  572. * Nullterminierte via-Liste, auf die idl zeigt, in den Framebuffer, auf    *
  573. * dessen Kopf mbhd zeigt, uebertragen. Die Nullterminierung nicht ueber-   *
  574. * tragen, aber am Ende der via-Liste das letzte Zeichen der via-Liste mit  *
  575. * dem HDLC End-Of-Address-Bit uebertragen.                                 *
  576. *                                                                          *
  577. \**************************************************************************/
  578.  
  579. VOID putvia(idl,mbhd)
  580.  
  581. char     *idl;
  582. MBHEAD   *mbhd;
  583.  
  584.   {
  585.     while (*idl != '\0')                /* gesamte via-Liste in den       */
  586.       {                                 /* Framebuffer uebertragen        */
  587.         putfid(idl,mbhd);
  588.         idl += L2IDLEN;
  589.       }                                 /* dann                           */
  590.     *(mbhd->mbbp - 1) |= L2CEOA;        /* EoA direkt im Buffer setzen    */
  591.   }
  592.  
  593.  
  594.  
  595.  
  596.  
  597. /**************************************************************************\
  598. *                                                                          *
  599. * "put frame id"                                                           *
  600. *                                                                          *
  601. * ID (Call und SSID, SSID wie im Frame), auf die id zeigt, in den          *
  602. * Framebuffer, auf dessen Kopf mbhd zeigt, uebertragen. Dabei Call von     *
  603. * ASCII in Frameformat (1 Bit linksgeschoben) umwandeln.                   *
  604. *                                                                          *
  605. \**************************************************************************/
  606.  
  607. VOID putfid(id,mbhd)
  608.  
  609. char     *id;
  610. MBHEAD   *mbhd;
  611.  
  612.   {
  613.     static unsigned n;                  /* Zaehler Call-Laenge            */
  614.  
  615.     for (n = 0; n < L2CALEN; ++n)       /* Call uebertragen in Buffer,    */
  616.       putchr(*id++ << 1,mbhd);          /* 1 Bit linksgeschoben           */
  617.     putchr(*id,mbhd);                   /* SSID unveraendert uebertragen  */
  618.   }
  619.  
  620.  
  621.  
  622.  
  623.  
  624. /**************************************************************************\
  625. *                                                                          *
  626. * "is to me"                                                               *
  627. *                                                                          *
  628. * Pruefen, ob die ID (Call + SSID, SSID wie im Frame), auf die id zeigt,   *
  629. * mit der ID der eigenen Station (myid) uebereinstimmt (SSID wird ohne     *
  630. * Steuerbits verglichen), oder ob das Call, auf das id zeigt, mit dem      *
  631. * symbolischen Namen (alias) der eigenen Station uebereinstimmt.           *
  632. *                                                                          *
  633. * Return :  TRUE  - myid stimmt mit id ueberein oder alias mit dem         *
  634. *                   call in id                                             *
  635. *           FALSE - sonst                                                  *
  636. *                                                                          *
  637. * FEF Alias-Name wird nicht mehr getestet                                  *
  638. *                                                                          *
  639. \**************************************************************************/
  640.  
  641. BOOLEAN istome(id)
  642.  
  643. char *id;
  644.  
  645.   {
  646.     return (cmpid(myid,id) == TRUE);
  647.   }
  648.  
  649.  
  650.  
  651.  
  652.  
  653. /**************************************************************************\
  654. *                                                                          *
  655. * "compare calls"                                                          *
  656. *                                                                          *
  657. * Calls miteinander vergleichen.                                           *
  658. *                                                                          *
  659. * Return :  TRUE  - die Calls stimmen ueberein                             *
  660. *           FALSE - die Calls stimmen nicht ueberein oder mindestens eins  *
  661. *                   der Calls beginnt mit einem Blank                      *
  662. *                                                                          *
  663. \**************************************************************************/
  664.  
  665. BOOLEAN cmpcal(call1,call2)
  666.  
  667. char *call1;
  668. char *call2;
  669.  
  670.   {
  671.     static unsigned n;                                 /* Zaehler         */
  672.  
  673.     for (n = 0; n < L2CALEN; ++n)                      /* jedes Zeichen   */
  674.       if (    (!n && (*call2 == ' ' || *call1 == ' ')) /* 1. Zeich. ' ' ? */
  675.            || (*call2++ != *call1++)                   /* sonst gleich ?  */
  676.          ) return (NO);                                /* nein            */
  677.     return (YES);                                      /* ja, alle gleich */
  678.   }
  679.  
  680.  
  681.  
  682.  
  683.  
  684. /**************************************************************************\
  685. *                                                                          *
  686. * "compare ID list"                                                        *
  687. *                                                                          *
  688. * Nullterminierte ID-Listen (Calls + SSID's, SSID wie im Frame)            *
  689. * miteinander vergleichen (SSID nur reine SSID 0-15 vergleichen ohne       *
  690. * Steuerbits).                                                             *
  691. *                                                                          *
  692. * Return :  TRUE  - die ID-Listen stimmen ueberein                         *
  693. *           FALSE - sonst                                                  *
  694. *                                                                          *
  695. \**************************************************************************/
  696.  
  697. BOOLEAN cmpidl(idl1,idl2)
  698.  
  699. char *idl1;
  700. char *idl2;
  701.  
  702.   {
  703.     while (*idl2 != '\0')                         /* bis Liste 2 zuende   */
  704.       {
  705.         if (!cmpid(idl1,idl2)) return (NO);       /* ID's vergleichen     */
  706.         idl2 += L2IDLEN;                          /* Zeiger auf naechste  */
  707.         idl1 += L2IDLEN;                          /* ID's                 */
  708.       }                                           /* Listen gleich, wenn  */
  709.     return (!*idl1);                              /* beide zuende         */
  710.   }
  711.  
  712.  
  713.  
  714.  
  715.  
  716. /**************************************************************************\
  717. *                                                                          *
  718. * "compare ID's"                                                           *
  719. *                                                                          *
  720. * ID's (Call + SSID, SSID wie im Frame) miteinander vergleichen (SSID nur  *
  721. * reine SSID 0-15 vergleichen ohne Steuerbits).                            *
  722. *                                                                          *
  723. * Return :  TRUE  - die ID's stimmen ueberein                              *
  724. *           FALSE - sonst                                                  *
  725. *                                                                          *
  726. \**************************************************************************/
  727.  
  728. BOOLEAN cmpid(id1,id2)
  729.  
  730. char *id1;
  731. char *id2;
  732.  
  733.   {
  734.     static unsigned n;                            /* Zaehler              */
  735.  
  736.     for (n = 0; n < L2CALEN; ++n)                 /* Calls vergleichen    */
  737.       if (*id2++ != *id1++) return (NO);
  738.     return ((*id2 & 0x1E) == (*id1 & 0x1E));      /* reine SSID vergl.    */
  739.   }
  740.  
  741.  
  742.  
  743.  
  744.  
  745. /**************************************************************************\
  746. *                                                                          *
  747. * "copy ID list"                                                           *
  748. *                                                                          *
  749. * Nullterminierte ID-Liste (Calls + SSID's, SSID wie im Frame) von source  *
  750. * nach dest kopieren, Zielliste mit '\0' abschliessen.                     *
  751. *                                                                          *
  752. \**************************************************************************/
  753.  
  754. VOID cpyidl(dest,source)
  755.  
  756. char *dest;
  757. char *source;
  758.  
  759.   {
  760.     while (*source != '\0')             /* solange Liste nicht zuende     */
  761.       {
  762.         cpyid(dest,source);             /* ID kopieren                    */
  763.         source += L2IDLEN;              /* Zeiger um eine ID-Laenge       */
  764.         dest += L2IDLEN;                /* weiter                         */
  765.       }
  766.     *dest = '\0';                       /* Zielliste abschliessen         */
  767.   }
  768.  
  769.  
  770.  
  771.  
  772.  
  773. /**************************************************************************\
  774. *                                                                          *
  775. * "copy ID"                                                                *
  776. *                                                                          *
  777. * Komplette ID (Call + SSID, SSID wie im Frame), auf die source zeigt,     *
  778. * nach dest kopieren. In der kopierten SSID das End-Of-Address-Bit und das *
  779. * Command/Response/Has-Been-Repeated-Bit loeschen.                         *
  780. *                                                                          *
  781. \**************************************************************************/
  782.  
  783. VOID cpyid(dest,source)
  784.  
  785. char *dest;
  786. char *source;
  787.  
  788.   {
  789.     static unsigned n;                    /* Laengenzaehler               */
  790.  
  791.     for (n = 0; n < L2CALEN; ++n)         /* Call kopieren                */
  792.       *dest++ = *source++;
  793.     *dest = *source & ~(L2CEOA | L2CCR);  /* SSID kopieren, Bits loeschen */
  794.   }
  795.  
  796.  
  797.  
  798.  
  799.  
  800. /**************************************************************************\
  801. *                                                                          *
  802. * "deallocate message list"                                                *
  803. *                                                                          *
  804. * Komplette Messageliste, auf deren Listenkopf mlp zeigt, deallokieren.    *
  805. * D.h. alle Messagespeicher (jeweils Kopf und daran haengende Datenbuffer) *
  806. * deallokieren.                                                            *
  807. *                                                                          *
  808. *                                                                          *
  809. *            +--------+    +--------+               +--------+             *
  810. *    mlp --->| head   |--->|        |--->       --->|        |---> mlp     *
  811. *            +--------+    +--------+      ...      +--------+             *
  812. *      b <---| tail   |<---|        |<---       <---|        |<--- b       *
  813. *            +--------+    +--------+               +--------+             *
  814. *                          |        |---> \         |        |---> \       *
  815. *                          +        +      |        +        +      |      *
  816. *                          |        |<--- /|        |        |<--- /|      *
  817. *                          +--------+      |        +--------+      |      *
  818. *                          |        |      |        |        |      |      *
  819. *                                          |                        |      *
  820. *      deallokieren                        |------------------------|      *
  821. *                                            siehe unten dealmb()          *
  822. *                                                                          *
  823. \**************************************************************************/
  824.  
  825. VOID dealml(mlp)
  826.  
  827. LEHEAD *mlp;
  828.  
  829.   {
  830.     static MBHEAD *bp;                  /* Zeiger auf Messagebufferhead   */
  831.  
  832.     LOOP                                /* fuer alle Messagebufferheads   */
  833.       {                                 /* in Messagespeicherliste :      */
  834.         DIinc();                        /* Listenkonsistenz !             */
  835.         bp = mlp->nextle;               /* Zeiger auf naechsten Msgbhead  */
  836.         decEI();                        /* Interrupts wieder erlauben     */
  837.         if (mlp == bp) break;           /* Schwanz beisst Kopf -> fertig  */
  838.         dealmb(unlink(bp));             /* sonst Messagespeicher deallok. */
  839.       }
  840.   }
  841.  
  842.  
  843.  
  844.  
  845.  
  846. /**************************************************************************\
  847. *                                                                          *
  848. * "deallocate message buffer"                                              *
  849. *                                                                          *
  850. * Einen kompletten Messagespeicher, auf dessen Kopf mbhd zeigt,            *
  851. * deallokieren, d.h. sowohl den Messagebufferhead als auch alle an dessen  *
  852. * Messagebufferliste haengende Datenbuffer deallokieren.                   *
  853. *                                                                          *
  854. *                                                                          *
  855. *            +--------+           deallokieren                             *
  856. *    mbhd -->|        |                                                    *
  857. *            +--------+                                                    *
  858. *            |        |                                                    *
  859. *            +--------+      +--------+                +--------+          *
  860. *      a --->|        |----->|        |--->        --->|        |---> a    *
  861. *            +  mbl   +      +--------+      ...       +--------+          *
  862. *      b <---|        |<-----|        |<---        <---|        |<--- b    *
  863. *            +--------+      +--------+                +--------+          *
  864. *            |        |      |        |                |        |          *
  865. *                                                                          *
  866. \**************************************************************************/
  867.  
  868. VOID dealmb(mbhd)
  869.  
  870. MBHEAD *mbhd;
  871.  
  872.   {
  873.     static MB *bp;                                /* Datenbufferzeiger    */
  874.  
  875.     while ((bp = mbhd->mbl.head) != &mbhd->mbl)   /* alle Datenbuffer     */
  876.       dealoc(unlink(bp));
  877.     dealoc(mbhd);                                 /* am Ende den Kopf     */
  878.   }
  879.  
  880.  
  881.  
  882.  
  883.  
  884. /**************************************************************************\
  885. *                                                                          *
  886. * "deallocate"                                                             *
  887. *                                                                          *
  888. * Buffer, auf den bp zeigt, initialisieren als neuen Messagebufferhead     *
  889. * (rwndmb()) und deallokieren, d.h. in die Freiliste freel einhaengen und  *
  890. * den Freibufferzaehler nmbfre inkrementieren.                             *
  891. *                                                                          *
  892. *                                                                          *
  893. *            +--------+                                                    *
  894. *     bp --->|        |         deallokieren                               *
  895. *            +--------+                                                    *
  896. *            |        |                                                    *
  897. *            +--------+                                                    *
  898. *            |        |                                                    *
  899. *                                                                          *
  900. \**************************************************************************/
  901.  
  902. VOID dealoc(bp)
  903.  
  904. MBHEAD *bp;
  905.  
  906.   {
  907.       bp->mbl.head                      /* als Messagehead initialisieren */
  908.     = bp->mbl.tail                      /*   Bufferlistenkopf             */
  909.     = &bp->mbl;                         /*   initialisieren               */
  910.     bp->mbpc = 0;                       /*   Message leer                 */
  911.     rwndmb(bp);                         /*   Rest initialisieren          */
  912.     DIinc();                            /* Listenkonsistenz !             */
  913.     relink(bp,freel.tail);              /* Buffer an Freiliste anhaengen  */
  914.     ++nmbfre;                           /* 1 Freibuffer mehr              */
  915.     decEI();                            /* Interrupts wieder erlauben     */
  916.   }
  917.  
  918.  
  919.  
  920.  
  921.  
  922. /**************************************************************************\
  923. *                                                                          *
  924. * "initialize head"                                                        *
  925. *                                                                          *
  926. * Listenkopf, auf den hd zeigt, initialisieren :                           *
  927. *                                                                          *
  928. *                                                                          *
  929. *                                              +----------------------+    *
  930. *                                              | +------------------+ |    *
  931. *                                              | |                  | |    *
  932. *            +--------+                        v v   +--------+     | |    *
  933. *     hd --->|        |         ->        hd ------->|        |-----+ |    *
  934. *            +--------+                              +--------+       |    *
  935. *            |        |                              |        |-------+    *
  936. *            +--------+                              +--------+            *
  937. *            |        |                              |        |            *
  938. *                                                                          *
  939. \**************************************************************************/
  940.  
  941. VOID inithd(hd)
  942.  
  943. LHEAD *hd;
  944.  
  945.   {
  946.     hd->head = hd->tail = hd;
  947.   }
  948.  
  949.  
  950.  
  951.  
  952.  
  953. /**************************************************************************\
  954. *                                                                          *
  955. * "level 2 to level x"                                                     *
  956. *                                                                          *
  957. * Meldung msg (L2M...) an Layer 7 weitergeben.                             *
  958. *                                                                          *
  959. \**************************************************************************/
  960.  
  961. VOID l2tolx(msg)
  962.  
  963. unsigned msg;
  964.  
  965.   {
  966.     l2tol7(msg,lnkpoi,2);               /* Layer 2  ->  Layer 7            */
  967.   }
  968.  
  969.  
  970.  
  971.  
  972.  
  973. /**************************************************************************\
  974. *                                                                          *
  975. * "uppercase"                                                              *
  976. *                                                                          *
  977. * Zeichen c in Grossbuchstabe umwandeln, wenn Kleinbuchstabe, und          *
  978. * zurueckgeben.                                                            *
  979. *                                                                          *
  980. \**************************************************************************/
  981.  
  982. upcase(c)
  983.  
  984. char c;
  985.  
  986.   {
  987.     return ( ('a' > c || 'z' < c) ? c : c - ('a' - 'A') );
  988.   }
  989.  
  990.  
  991.  
  992. /* Ende von L2C.C */
  993.